import cmd
import sys
from common import *


class SimpleDBShell(cmd.Cmd):
    """
    一个简单的内存键值数据库交互式Shell，演示交互式终端界面的使用。
    """

    # 1. 自定义欢迎语和提示符
    lines = [
        "     欢迎使用 SimpleShell v1.0 (基于 cmd 库) ",
        " ",
        "这是一个简单的内存键值数据库，当程序退出时，所有数据将丢失",
        "在后续的代码中，这些功能将被保留",
        " ",
        "set <key> <value>  - 设置一个键值对 (值可以包含空格)",
        "get <key>          - 获取一个键对应的值",
        "delete <key>       - 删除一个键值对",
        "list               - 列出所有存储的键值对",
        "help               - 显示帮助信息",
        "exit / quit        - 退出程序"
    ]
    intro = create_aligned_intro(lines)
    prompt = "db> "

    def __init__(self):
        """
        构造函数，初始化父类并创建一个用于存储数据的字典。
        """
        super().__init__()
        # 2. 在实例中维护状态（这里是一个字典作为内存数据库）
        self.data = {}

    # 3. 为每个命令实现一个 `do_<command>` 方法
    def do_set(self, arg):
        """
        设置一个键值对。用法: set <key> <value>
        值部分可以包含空格。
        """
        # `arg` 是用户在命令后输入的所有内容
        if not arg:
            print("❌ 错误: 'set' 命令需要一个键和一个值。")
            print("   用法: set <key> <value>")
            return

        # 使用 split(None, 1) 可以很好地处理值中包含空格的情况
        parts = arg.split(None, 1)
        if len(parts) < 2:
            print("❌ 错误: 请同时提供键和值。")
            print("   用法: set <key> <value>")
            return

        key, value = parts
        self.data[key] = value
        print(f"✅ 成功: '{key}' 已设置为 '{value}'")

    def do_get(self, arg):
        """
        根据键获取值。用法: get <key>
        """
        key = arg.strip()
        if not key:
            print("❌ 错误: 'get' 命令需要一个键。")
            print("   用法: get <key>")
            return

        value = self.data.get(key)
        if value is not None:
            print(f"➡️ {key} = {value}")
        else:
            print(f"🔍 未找到键: '{key}'")

    def do_delete(self, arg):
        """
        根据键删除一个键值对。用法: delete <key>
        """
        key = arg.strip()
        if not key:
            print("❌ 错误: 'delete' 命令需要一个键。")
            print("   用法: delete <key>")
            return

        if key in self.data:
            del self.data[key]
            print(f"✅ 成功: 键 '{key}' 已被删除。")
        else:
            print(f"🔍 未找到键: '{key}'")

    def do_list(self, arg):
        """
        列出所有存储的键值对。
        """
        if not self.data:
            print("ℹ️  数据库为空。")
            return

        print("📋 当前存储的所有数据:")
        max_key_len = max(len(k) for k in self.data.keys()) if self.data else 0
        for key, value in self.data.items():
            # 简单对齐，使输出更美观
            print(f"  - {key:<{max_key_len}} : {value}")

    # 4. 实现退出逻辑
    def do_exit(self, arg):
        """
        退出交互式Shell。
        """
        print("\n👋 感谢使用，再见！")
        return True  # 返回 True 会导致 cmdloop() 退出

    def do_quit(self, arg):
        """
        `quit` 是 `exit` 的别名。
        """
        return self.do_exit(arg)

    def do_EOF(self, arg):
        """
        处理 Ctrl+D 或Ctrl+Z 输入 (文件结束符)，实现优雅退出。
        """
        # `print()` 是为了在 ^D 后换行，使终端提示符在新的一行显示
        print()
        return self.do_exit(arg)

    # 5. (可选) 为特定命令提供更详细的帮助
    def help_set(self):
        print("\n".join([
            "命令: set <key> <value>",
            "功能: 创建或更新一个键值对。",
            "示例:",
            "  set name 'John Doe'  (设置一个带空格的值)",
            "  set age 30           (设置一个简单的值)"
        ]))

    # 6. (可选) 处理未知命令
    def default(self, line):
        """
        处理所有未匹配到 do_* 方法的输入
        """
        print(f"❌ 未知命令: '{line}'。输入 'help' 查看可用命令列表。")


def main():
    """
    程序主入口。
    """
    try:
        # 启动 cmd 循环
        SimpleDBShell().cmdloop()
    except KeyboardInterrupt:
        # 处理 Ctrl+C，实现退出
        print("\n👋 检测到中断，程序退出。")
        sys.exit(0)


if __name__ == '__main__':
    main()